/*
 * CSocket.h
 *
 *  Created on: 6 oct. 2009
 *      Author: Maxime Gaudin
 */

#ifndef SOCKETS_HEADER
	#define SOCKETS_HEADER
	#include <sys/socket.h>
	#include <arpa/inet.h>
	#include <stdlib.h>
	#include <string.h>
	#include <unistd.h>
	#include <netinet/in.h>
	#include <netdb.h>
#endif

#ifndef IOSTREAM_HEADER
	#define IOSTREAM_HEADER
	#include <iostream>
#endif

#ifndef STRING_HEADER
    #include <string>
    #define STRING_HEADER
#endif

#ifndef CSOCKET_H_
#define CSOCKET_H_

#define BUFFSIZE 2048

enum SocketState
{
	NONE,			// Le socket n'existe pas encore
	IDLE,			// Le socket a été crée mais il n'a jamais été connecté
	CONNECTING,		// Le socket est en train de se connecter
	ERR_CONNECTING,	// Il y a eu une erreur pendant la connexion
	CONNECTED,		// Le socket est connecté
	SENDING,		// Le socket est en train d'envoyer des données
	ERR_SENDING,	// Il y a eu une erreur pendant l'envoi de donnée
	RECEIVING,		// Le socket reçoit des données
	ERR_RECEIVING,	// Il y a eu une erreur pendant le réception des données
	CLOSED			// Le socket a été déconnecté
};

class CSocket {
// Constructeurs & Destructeurs ================================================================================
	public:
		CSocket(std::string ServerAddr, int ServerPort);
		// ServerAddr : Adresse du serveur sous la forme domaine.ext (e.g google.fr)
		// ServerPort : Port de connexion du socket
		// Contrat : L'adresse du serveur doit être de la bonne forme et le serveur doit exister.
		// La méthode va crée un socket


// Getter ======================================================================================================
	public:
		SocketState getState();
		// Retourne l'état du socket

// Méthodes publiques ==========================================================================================
	public:
		int Connect();
		// Connecte le socket au serveur et au port spécifié dans le constructeur
		// Retourne -1 en cas d'échec, 0 sinon

		int Connect(std::string ServerAddr, int ServerPort);
		// ServerAddr : Adresse du serveur sous la forme domaine.ext (e.g google.fr)
		// ServerPort : Port de connexion du socket
		// Contrat : L'adresse du serveur doit être de la bonne forme et le serveur doit exister.
		// Connecte le socket au nouveau server et au nouveau port spécifiés en paramètre
		// Retourne -1 en cas d'échec, 0 sinon

		void Disconnect();
		// Déconnect le socket

		int Send(std::string Data);
		// Data : Chaine de caractère en envoyer
		// Envoi la chaine de caractère au serveur o`u le socket est connecté
		// Retourne -1 en cas d'échec, 0 sinon

		int Send(char* Data, unsigned int Size);
		// Data : Octets à envoyer
		// Size : Nombre d'octets à envoyer
		// Envoi le tableau d'octets au serveur o`u le socket est connecté
		// Retourne -1 en cas d'échec, 0 sinon

		char* Receive();
		// Recoi le tableau d'octet de Taille #BUFFSIZE du serveurs
		// Renvoi NULL en cas d'échec, sinon les données reçues

		char* Receive(int BufferSize);
		// BufferSize : Taille du Buffer à utiliser.
		// Recoi le tableau d'octet de Taille BufferSize du serveurs
		// Renvoi NULL en cas d'échec, sinon les données reçues

		char* ResolveHostByName(std::string Hostname);
		// HostName : Adresse du serveur sous la forme domain.ext
		// Convertit une adresse en adresse système
		// Retourne NULL si l'hôte n'existe pas.

// Méthodes privées ============================================================================================
	private:
		int createSocket();
		// Crée un socket.
		// Renvoi -1 en cas d'échec, sinon l'ID du socket

	private:
		int socketID;
		SocketState state;

		std::string serverAddr;
		int serverPort;
};

#endif /* CSOCKET_H_ */
